package org.wattdepot.cli.commands;

import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;

/**
 * This class tests the total sampling command of the 
 * CommandLineInterface's actual commands.
 * @author David Mau
 */
public class TestCommandTotalSampling {
  String cr = System.getProperty("line.separator");
  // Variable to make PMD stop triggering the String Literal error.
  String carbon = "carbon";
  String energy = "energy";
  String testdate = "2009-11-15";
  
  /**
   * Test normal operation of the totalSamplings command.
   */
  @Test
  public void testTotalSamplings() {
    // Create a new total sampling command object.
    TotalSamplingCommand command = new TotalSamplingCommand(null);
    // Create a new List to store the args
    List<String> args = Arrays.asList( carbon, "SIM_KAHE", "2009-10-31", "60" );
    
    // Get the output from the command
    String sourceOutput = command.doCommand( args );
    
    // Ready the output that we know is true
    String knownOutput = "2.169689472E7 pounds";
    knownOutput = knownOutput.concat(cr);
    
    // Compare the two to see if they are the same.
    int result = sourceOutput.compareTo(knownOutput);
    assertSame("Checking known carbon at Kahe's grid with good timestamp", result, 0);
    
    // Create a new List to store the args
    args = Arrays.asList( carbon, "SIM_WAIAU_8", testdate, "30" );
    
    // Get the output from the command
    sourceOutput = command.doCommand( args );

    // Ready the output that we know is true
    knownOutput = "3088648.0 pounds";
    knownOutput = knownOutput.concat(cr);
    
    // Compare the two to see if they are the same.
    result = sourceOutput.compareTo(knownOutput);
    assertSame("Checking known carbon at Waiau #8 with good timestamp", result, 0);
    
    // Create a new List to store the args
    args = Arrays.asList( carbon, "SIM_OAHU_GRID", testdate, "30" );
    
    // Get the output from the command
    sourceOutput = command.doCommand( args );

    // Ready the output that we know is true
    knownOutput = "2.7852974666666664E7 pounds";
    knownOutput = knownOutput.concat(cr);

    // Compare the two to see if they are the same.
    result = sourceOutput.compareTo(knownOutput);
    assertSame("Checking known carbon at Oahu's grid with good timestamp", result, 0);

    // Create a new List to store the args
    args = Arrays.asList( energy, "SIM_KAHE", "2009-10-31", "60" );
    
    // Get the output from the command
    sourceOutput = command.doCommand( args );

    // Ready the output that we know is true
    knownOutput = "12440.88 MegaWatt-Hours";
    knownOutput = knownOutput.concat(cr);
    
    // Compare the two to see if they are the same.
    result = sourceOutput.compareTo(knownOutput);
    assertSame("Checking known energy at Kahe's grid with good timestamp", result, 0);
    
    // Create a new List to store the args
    args = Arrays.asList( energy, "SIM_WAIAU_8", testdate, "30" );
    
    // Get the output from the command
    sourceOutput = command.doCommand( args );

    // Ready the output that we know is true
    knownOutput = "1715.9155555555556 MegaWatt-Hours";
    knownOutput = knownOutput.concat(cr);
    
    // Compare the two to see if they are the same.
    result = sourceOutput.compareTo(knownOutput);
    assertSame("Checking known energy at Waiau #8 with good timestamp", result, 0);
    
    // Create a new List to store the args
    args = Arrays.asList( energy, "SIM_OAHU_GRID", testdate, "30" );
    
    // Get the output from the command
    sourceOutput = command.doCommand( args );

    // Ready the output that we know is true
    knownOutput = "14072.115555555558 MegaWatt-Hours";
    knownOutput = knownOutput.concat(cr);

    // Compare the two to see if they are the same.
    result = sourceOutput.compareTo(knownOutput);
    assertSame("Checking known energy at Oahu's grid with good timestamp", result, 0);

  }

  /**
   * Test bad timestamp detection for the totalSampling command.
   */
  @Test
  public void testTotalSamplingsBadTime() {
    // Create a new total sampling command object.
    TotalSamplingCommand command = new TotalSamplingCommand(null);
    // Create a new List to store the args
    List<String> args = Arrays.asList( carbon, "SIM_KALAELOA", "007", "60" );
    
    // Get the output from the command
    String sourceOutput = command.doCommand( args );
    
    // Check to see if the correct error returned
    assertTrue("Checking for correct response to a bad timestamp", sourceOutput
        .contains(WattDepotCliCommand.badTimeStamp));

  }

  
  /**
   * Test bad source detection for the totalSampling command.
   */
  @Test
  public void testTotalSamplingBadSource() {
    // Create a new total sampling command object.
    TotalSamplingCommand command = new TotalSamplingCommand(null);
    
    // Attempt to use a bad source with carbon
    // Create a new List to store the args
    List<String> args = Arrays.asList( carbon, "ZOO", "2009-10-30", "30" );
    
    // Get the output from the command
    String sourceOutput = command.doCommand( args );
    
    // Check to see if the correct error returned
    assertTrue("Checking for correct response to a bad carbon source", sourceOutput
        .contains(WattDepotCliCommand.resourceNotFound));
    
    // Attempt to use a bad source with energy
    // Create a new List to store the args
    args = Arrays.asList( energy, "MOON", "2009-10-29", "30" );
    
    // Get the output from the command
    sourceOutput = command.doCommand( args );
    
    // Check to see if the correct error returned
    assertTrue("Checking for correct response to a bad energy source", sourceOutput
        .contains(WattDepotCliCommand.resourceNotFound));

  }

  /**
   * Test bad option given for carbon or energy for the totalSampling command.
   */
  @Test
  public void testTotalSamplingBadOption() {
    // Attempt to use a bad option
    // Create a new total sampling command object.
    TotalSamplingCommand command = new TotalSamplingCommand(null);
    // Create a new List to store the args
    List<String> args = Arrays.asList( "black hole", "SIM_AES", "2009-10-20", "60" );
    
    // Get the output from the command
    String sourceOutput = command.doCommand( args );
    
    // Check to see if the correct error returned
    assertTrue("Checking for correct response to a bad option", sourceOutput
        .contains(WattDepotCliCommand.carbonOrEnergy));
    
  }


  /**
   * Test a bad interval given for the totalSampling command. The given String should be convertible
   * into an Integer.
   */
  @Test
  public void testTotalSamplingBadInterval() {
    // Attempt to use a bad interval
    // Create a new total sampling command object.
    TotalSamplingCommand command = new TotalSamplingCommand(null);
    // Create a new List to store the args
    List<String> args = Arrays.asList( carbon, "SIM_OAHU", "2009-11-01", "ants" );
    
    // Get the output from the command
    String sourceOutput = command.doCommand( args );
    
    // Check to see if the correct error returned
    assertTrue("Checking for correct response to a bad interval", sourceOutput
        .contains(WattDepotCliCommand.intervalNotNumber));
    
  }

  /**
   * Test another bad interval given for the totalSampling command. The given String should be a
   * non-zero, positive integer.
   */
  @Test
  public void testTotalSamplingBadIntervalInteger() {
    // Create a new total sampling command object.
    TotalSamplingCommand command = new TotalSamplingCommand(null);
    
    // Attempt to use a negative interval
    // Create a new List to store the args
    List<String> args = Arrays.asList( carbon, "SIM_WAIAU", "2009-10-25", "-1" );
    
    // Get the output from the command
    String sourceOutput = command.doCommand( args );
    
    // Check to see if the correct error returned
    assertTrue("Checking for correct response to a negative interval", sourceOutput
        .contains(WattDepotCliCommand.intervalNegativeOrZero));
    
    // Attempt to use zero interval
    // Create a new List to store the args
    args = Arrays.asList( energy, "SIM_HPOWER", "2009-10-20", "0" );
    
    // Get the output from the command
    sourceOutput = command.doCommand( args );
    
    // Check to see if the correct error returned
    assertTrue("Checking for correct response to a zero interval", sourceOutput
        .contains(WattDepotCliCommand.intervalNegativeOrZero));
  }  

  /**
   * Tests to see if the TotalSampling command can handle excess arguments.
   */
  @Test
  public void testExcessArguments() {
    // Create a new total sampling command object.
    TotalSamplingCommand command = new TotalSamplingCommand(null);
    // Create a new List to store the args
    List<String> args = Arrays.asList("1", "2", "3", "4", "5");
    
    // Get the output from the command
    String sourceOutput = command.doCommand( args );

    // Make sure that the command is returning the error properly
    assertTrue("Checking excess TotalSampling argument handling", 
        sourceOutput.contains(WattDepotCliCommand.tooManyArguments));
  }
  
  /**
   * Tests to see if the TotalSampling command can handle not enough arguments.
   */
  @Test
  public void testFewArguments() {
    // Create a new total sampling command object.
    TotalSamplingCommand command = new TotalSamplingCommand(null);
    // Create a new List to store the args
    List<String> args = Arrays.asList("1");
    
    // Get the output from the command
    String sourceOutput = command.doCommand( args );

    // Make sure that the command is returning the error properly
    assertTrue("Checking TotalSampling handling not enough arguments", 
        sourceOutput.contains(WattDepotCliCommand.missingArguments));
  }
}
